package de.e2it3t.schulverwaltung.ui;

import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.validation.ValidationResult;
import com.jgoodies.validation.ValidationResultModel;
import com.jgoodies.validation.util.DefaultValidationResultModel;
import com.jgoodies.validation.view.ValidationResultViewFactory;
import de.e2it3t.schulverwaltung.App;
import de.e2it3t.schulverwaltung.data.Fach;
import de.e2it3t.schulverwaltung.data.Klasse;
import de.e2it3t.schulverwaltung.data.Lehreinheit;
import de.e2it3t.schulverwaltung.data.Lehrer;
import de.e2it3t.schulverwaltung.data.Raum;
import de.e2it3t.schulverwaltung.data.TimeHelper;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.sql.Time;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;

/**
 * Dialog für das Hinzufügen oder Bearbeiten einer Lehreinheit. <br>
 * <br>
 * Je nach verwendetem Konstruktor kann man einen Dialog zum Erstellen oder 
 * Bearbeiten einer bestehenden Lehreinheit anzeigen.<br>
 * <br>
 * Der Dialog sammelt Daten zu einer Lehreinheit. Wenn der Speichern-Button
 * gedrückt wird, werden die Daten validiert. Wenn die Eingaben ungültig sind,
 * die Lehreinheit bereits vorhanden ist oder mit anderen Lehreiheiten in den
 * selben Zeitraum fällt, dann werden entsprechende Meldungen angezeigt.
 * Wenn die Eingaben korrekt sind, wird die Lehreinheit in der Datenbank
 * gespeichert, der Dialog geschlossen und die View, welche den Dialog geöffnet
 * hat, aufgefordert, ihre Daten zu erneuern.
 * 
 * @author Viktor Reiser
 */
public class LehreinheitDialog extends JDialog {
    
    private AppView owner;
    
    private Klasse klasse;
    private Lehreinheit lehreinheit;
    
    private JButton saveButton;
    private JButton cancelButton;
    private JComboBox raumComboBox;
    private JComboBox lehrerComboBox;
    private JComboBox fachComboBox;
    private JTextField startUhrzeitTextField;
    private JTextField endeUhrzeitTextField;
    private JComboBox tagComboBox;
    
    private ValidationResultModel validationModel;
    
    private Raum[] raeume;
    private Fach[] faecher;
    private Lehrer[] lehrer;
    
    
    /**
     * Dialog zum Erstellen einer neuen Lehreinheit.
     * 
     * @param owner View, welche den Dialog geöffnet hat
     * @param klasseId Klassen ID, zu welcher die Lehreinheit gehört
     */
    public LehreinheitDialog(AppView owner, int klasseId) {
        this(owner, klasseId, 0);
    }
    
    public LehreinheitDialog(AppView owner, int klasseId, int day, Time time) {
        this(owner, klasseId, 0);
        
        tagComboBox.setSelectedIndex(day);
        time =  TimeHelper.clampToMinutesInterval(
                        time, App.getConfig().getMinutesInterval());
        startUhrzeitTextField.setText(TimeHelper.getTimeString(time));
    }
    
    /**
     * Dialog zum Bearbeiten einer bestehenden Lehreinheit.
     * 
     * @param owner View, welche den Dialog geöffnet hat
     * @param klasseId Klasse ID, zu welcher die Lehreinheit gehört
     * @param lehreinheitId ID der Lehreinheit; wenn die ID ungültig ist, wrid
     * ein Dialog zum Erstellen einer neuen Lehreinheit angezeigt
     */
    public LehreinheitDialog(AppView owner, int klasseId, int lehreinheitId) {
        setTitle("Neue Lehreinheit");
        setModal(true);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setMinimumSize(new Dimension(100, 100));
        
        validationModel = new DefaultValidationResultModel();
        
        this.owner = owner;
        
        if (lehreinheitId != 0) {
            lehreinheit = App.getDatabase().getLehreinheit(lehreinheitId);
            
            if (lehreinheit != null) {
                setTitle("Lehreinheit bearbeiten");
            }
            
            klasseId = lehreinheit.getKlasseId();
        }
        
        this.klasse = App.getDatabase().getKlasse(klasseId);
        
        setupUi();
    }
    
    private void setupUiComponents() {
        saveButton = new JButton("Speichern");
        saveButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                validateAndSave();
            }
        });
        
        cancelButton = new JButton("Abbrechen");
        cancelButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                dispose();
            }
        });
        
        raeume = App.getDatabase().getRaeume().toArray(new Raum[0]);
        raumComboBox = new JComboBox(raeume);
        
        ActionListener fachActionListener = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                Fach fach = faecher[fachComboBox.getSelectedIndex()];
                lehrer = App.getDatabase()
                        .getLehrer(fach.getId()).toArray(new Lehrer[0]);
                lehrerComboBox.setModel(new DefaultComboBoxModel(lehrer));
            }
        };
        
        faecher = App.getDatabase().getFaecherMitLehrern().toArray(new Fach[0]);
        fachComboBox = new JComboBox(faecher);
        fachComboBox.addActionListener(fachActionListener);
        
        lehrerComboBox = new JComboBox();
        startUhrzeitTextField = new JTextField();
        startUhrzeitTextField.addFocusListener(new FocusAdapter() {
            @Override
            public void focusLost(FocusEvent e) {
                Time time = TimeHelper.getTimeFromString(
                        startUhrzeitTextField.getText());
                time =  TimeHelper.clampToMinutesInterval(
                        time, App.getConfig().getMinutesInterval());
                startUhrzeitTextField.setText(
                        TimeHelper.getTimeString(time));
            }
        });
        endeUhrzeitTextField = new JTextField();
        endeUhrzeitTextField.addFocusListener(new FocusAdapter() {
            @Override
            public void focusLost(FocusEvent e) {
                Time time = TimeHelper.getTimeFromString(
                        endeUhrzeitTextField.getText());
                time =  TimeHelper.clampToMinutesInterval(
                        time, App.getConfig().getMinutesInterval());
                endeUhrzeitTextField.setText(
                        TimeHelper.getTimeString(time));
            }
        });
        
        String[] days = new String[5];
        
        for (int i = 0; i < days.length; i++) {
            days[i] = TimeHelper.getDayString(i);
        }
        
        tagComboBox = new JComboBox(days);
        
        if (faecher.length != 0) {
            fachActionListener.actionPerformed(null);
        }
    }
    
    private void setupLehreinheit() {
        if (lehreinheit == null) {
            return;
        }
        
        for (Raum raum : raeume) {
            if (raum.getId() == lehreinheit.getRaumId()) {
                raumComboBox.setSelectedItem(raum);
                break;
            }
        }
        
        for (Fach fach : faecher) {
            if (fach.getId() == lehreinheit.getFachId()) {
                fachComboBox.setSelectedItem(fach);
                break;
            }
        }
        
        for (Lehrer lehrer : this.lehrer) {
            if (lehrer.getId() == lehreinheit.getLehrerId()) {
                lehrerComboBox.setSelectedItem(lehrer);
                break;
            }
        }
        
        tagComboBox.setSelectedIndex(lehreinheit.getTag());
        
        startUhrzeitTextField.setText(TimeHelper.getTimeString(
                lehreinheit.getUhrzeitBeginn()));
        endeUhrzeitTextField.setText(TimeHelper.getTimeString(
                lehreinheit.getUhrzeitEnde()));
    }
    
    private void setupUi() {
        setupUiComponents();
        setupLehreinheit();
        
        PanelBuilder pb = new PanelBuilder(new FormLayout(
                "pref, 5px, pref, 5px, pref"));
        CellConstraints cc = new CellConstraints();
        
        addToPanel(pb, cc, "Raum", raumComboBox);
        addToPanel(pb, cc, "Fach", fachComboBox);
        addToPanel(pb, cc, "Lehrer", lehrerComboBox);
        addToPanel(pb, cc, "Tag", tagComboBox);
        addToPanel(pb, cc, "Uhrzeit | Beginn", startUhrzeitTextField);
        addToPanel(pb, cc, "Uhrzeit | Ende", endeUhrzeitTextField);
        
        JComponent errorList = ValidationResultViewFactory.createReportList(
                validationModel);
        errorList.setPreferredSize(new Dimension(10, 80));
        
        pb.appendRow("pref");
        pb.add(errorList, cc.xyw(1, pb.getRow(), 5));
        pb.nextLine();
        
        pb.appendRow("15px");
        pb.nextLine();
        
        pb.appendRow("pref");
        pb.add(saveButton, cc.xy(3, pb.getRow()));
        pb.add(cancelButton, cc.xy(5, pb.getRow()));
        pb.nextLine();
        
        
        JPanel content = pb.getPanel();
        content.setBorder(new EmptyBorder(10, 10, 10, 10));
        
        setLayout(new BorderLayout());
        add(content, BorderLayout.CENTER);
        
        pack();
        setResizable(false);
        setLocationRelativeTo(null);
    }
    
    private void addToPanel(PanelBuilder pb, CellConstraints cc, String label,
            JComponent component) {
        
        pb.appendRow("pref");
        pb.addLabel(label, cc.xy(1, pb.getRow()));
        pb.add(component, cc.xyw(3, pb.getRow(), 3));
        pb.nextLine();
        
        pb.appendRow("5px");
        pb.nextLine();
    }
    
    private void validateAndSave() {
        ValidationResult result = new ValidationResult();
        
        Lehreinheit lehreinheit = new Lehreinheit();
        lehreinheit.setKlasseId(klasse.getId());
        lehreinheit.setTag(tagComboBox.getSelectedIndex());
        
        if (this.lehreinheit != null) {
            lehreinheit.setId(this.lehreinheit.getId());
        }
        
        if (raumComboBox.getSelectedIndex() == -1) {
            result.addError("Raum wählen!");
        } else {
            lehreinheit.setRaumId(raeume[raumComboBox.getSelectedIndex()].getId());
        }
        
        if (fachComboBox.getSelectedIndex() == -1) {
            result.addError("Fach wählen!");
        } else {
            lehreinheit.setFachId(faecher[fachComboBox.getSelectedIndex()].getId());
        }
        
        if (lehrerComboBox.getSelectedIndex() == -1) {
            result.addError("Lehrer wählen!");
        } else {
            lehreinheit.setLehrerId(lehrer[lehrerComboBox.getSelectedIndex()].getId());
        }
        
        lehreinheit.setUhrzeitBeginn(TimeHelper.getTimeFromString(
                startUhrzeitTextField.getText()));
        
        if (lehreinheit.getUhrzeitBeginn() == null) {
            result.addError("Beginn ist keine Uhrzeit (z.B. 13:20)!");
        } else if (TimeHelper.compareTime(
                lehreinheit.getUhrzeitBeginn(),
                App.getConfig().getMinimumTime()) < 0) {
            result.addError("Beginn darf nicht vor "
                    + TimeHelper.getTimeString(App.getConfig().getMinimumTime())
                    + " liegen!");
            lehreinheit.setUhrzeitBeginn(null);
        }
        
        lehreinheit.setUhrzeitEnde(TimeHelper.getTimeFromString(
                endeUhrzeitTextField.getText()));
        
        if (lehreinheit.getUhrzeitEnde() == null) {
            result.addError("Ende ist keine Uhrzeit (z.B. 13:20)!");
        } else if (TimeHelper.compareTime(
                lehreinheit.getUhrzeitEnde(),
                App.getConfig().getMaximumTime()) > 0) {
            result.addError("Ende darf nicht nach "
                    + TimeHelper.getTimeString(App.getConfig().getMaximumTime())
                    + " liegen!");
            lehreinheit.setUhrzeitEnde(null);
        }
        
        if (lehreinheit.getUhrzeitBeginn() != null
                && lehreinheit.getUhrzeitEnde() != null) {
            if (TimeHelper.getMinutesDiff(
                    lehreinheit.getUhrzeitBeginn(),
                    lehreinheit.getUhrzeitEnde()) < App.getConfig().getMinimumMinutes()) {
                result.addError("Eine Lehreinheit muss mindestens "
                        + App.getConfig().getMinimumMinutes()
                        + " Minuten lang sein!");
            } else if (App.getDatabase().hasLehreinheit(lehreinheit)) {
                result.addError("In dieser Zeit findet bereits eine Lehreinheit statt!");
            }
            
        }
        
        validationModel.setResult(result);
        pack();
        
        if (result.isEmpty()) {
            App.getDatabase().saveLehreinheit(lehreinheit);
            owner.refreshView();
            dispose();
        }
    }
}
